﻿@page "/game_2048"
@inject NavigationManager Navigation

<h1>2048</h1>

<div class="game-container">
    @for (int row = 0; row < GridSize; row++)
    {
        <div class="row">
            @for (int col = 0; col < GridSize; col++)
            {
                <div class="tile">@board[row, col]</div>
            }
        </div>
    }
</div>

<div class="controls">
    <button @onclick="MoveUp">⬆️</button>
    <div>
        <button @onclick="MoveLeft">⬅️</button>
        <button @onclick="MoveDown">⬇️</button>
        <button @onclick="MoveRight">➡️</button>
    </div>
</div>

<p>Score: @Score</p>
<p><button @onclick="RestartGame">重玩</button></p>

@if (isGameOver)
{
    <div class="game-over">
        <h2>游戏结束</h2>
        <button @onclick="RestartGame">重玩</button>
    </div>
}

@code {
    private const int GridSize = 4;
    private int[,] board = new int[GridSize, GridSize];
    private Random random = new Random();
    private int Score = 0;

    private bool isGameOver = false;

    // 记录移动前的状态用于比较
    private int[,] CloneBoard()
    {
        int[,] clone = new int[GridSize, GridSize];
        for (int i = 0; i < GridSize; i++)
        {
            for (int j = 0; j < GridSize; j++)
            {
                clone[i, j] = board[i, j];
            }
        }
        return clone;
    }

    // 检查两个棋盘状态是否相同
    private bool BoardsAreEqual(int[,] a, int[,] b)
    {
        for (int i = 0; i < GridSize; i++)
        {
            for (int j = 0; j < GridSize; j++)
            {
                if (a[i, j] != b[i, j])
                    return false;
            }
        }
        return true;
    }

    // 更新分数为当前最大方块的值
    private void UpdateScore()
    {
        int maxValue = 0;
        for (int i = 0; i < GridSize; i++)
        {
            for (int j = 0; j < GridSize; j++)
            {
                if (board[i, j] > maxValue)
                {
                    maxValue = board[i, j];
                }
            }
        }
        Score = maxValue;
    }

    private void AfterMove(bool moved)
    {
        // 只有移动后才添加新方块
        if (moved)
        {
            AddRandomTile();
            // 更新分数为当前最大方块的值
            UpdateScore();
        }

        if (IsGameOver())
        {
            isGameOver = true;
        }

        StateHasChanged();
    }

    private bool IsGameOver()
    {
        // 检查是否还有空位
        for (int row = 0; row < GridSize; row++)
        {
            for (int col = 0; col < GridSize; col++)
            {
                if (board[row, col] == 0)
                    return false;
            }
        }

        // 检查是否有可合并的相邻数字
        for (int row = 0; row < GridSize; row++)
        {
            for (int col = 0; col < GridSize; col++)
            {
                if (col < GridSize - 1 && board[row, col] == board[row, col + 1])
                    return false;
                if (row < GridSize - 1 && board[row, col] == board[row + 1, col])
                    return false;
            }
        }

        return true;
    }

    protected override void OnInitialized()
    {
        RestartGame();
    }

    private void RestartGame()
    {
        board = new int[GridSize, GridSize];
        Score = 0;
        AddRandomTile();
        AddRandomTile();
        UpdateScore(); // 初始化分数
        
        isGameOver = false;
    }

    private void AddRandomTile()
    {
        var emptyTiles = new List<(int, int)>();

        for (int row = 0; row < GridSize; row++)
        {
            for (int col = 0; col < GridSize; col++)
            {
                if (board[row, col] == 0)
                {
                    emptyTiles.Add((row, col));
                }
            }
        }

        if (emptyTiles.Count > 0)
        {
            var (row, col) = emptyTiles[random.Next(emptyTiles.Count)];
            board[row, col] = random.Next(1, 3) * 2; // Adds 2 or 4
        }
    }

    private void MoveLeft()
    {
        var originalBoard = CloneBoard();
        
        for (int row = 0; row < GridSize; row++)
        {
            var line = GetRow(row);
            var mergedLine = Merge(line);
            SetRow(row, mergedLine);
        }
        
        // 检查是否有移动
        bool moved = !BoardsAreEqual(originalBoard, board);
        AfterMove(moved);
    }

    private void MoveRight()
    {
        var originalBoard = CloneBoard();
        
        for (int row = 0; row < GridSize; row++)
        {
            var line = GetRow(row).Reverse().ToArray();
            var mergedLine = Merge(line).Reverse().ToArray();
            SetRow(row, mergedLine);
        }
        
        bool moved = !BoardsAreEqual(originalBoard, board);
        AfterMove(moved);
    }

    private void MoveUp()
    {
        var originalBoard = CloneBoard();
        
        for (int col = 0; col < GridSize; col++)
        {
            var line = GetColumn(col);
            var mergedLine = Merge(line);
            SetColumn(col, mergedLine);
        }
        
        bool moved = !BoardsAreEqual(originalBoard, board);
        AfterMove(moved);
    }

    private void MoveDown()
    {
        var originalBoard = CloneBoard();
        
        for (int col = 0; col < GridSize; col++)
        {
            var line = GetColumn(col).Reverse().ToArray();
            var mergedLine = Merge(line).Reverse().ToArray();
            SetColumn(col, mergedLine);
        }
        
        bool moved = !BoardsAreEqual(originalBoard, board);
        AfterMove(moved);
    }

    private int[] GetRow(int row)
    {
        var line = new int[GridSize];
        for (int col = 0; col < GridSize; col++)
        {
            line[col] = board[row, col];
        }
        return line;
    }

    private void SetRow(int row, int[] line)
    {
        for (int col = 0; col < GridSize; col++)
        {
            board[row, col] = line[col];
        }
    }

    private int[] GetColumn(int col)
    {
        var line = new int[GridSize];
        for (int row = 0; row < GridSize; row++)
        {
            line[row] = board[row, col];
        }
        return line;
    }

    private void SetColumn(int col, int[] line)
    {
        for (int row = 0; row < GridSize; row++)
        {
            board[row, col] = line[row];
        }
    }

    private int[] Merge(int[] line)
    {
        var merged = new List<int>();
        var skip = false;

        for (int i = 0; i < line.Length; i++)
        {
            if (line[i] == 0) continue;

            if (!skip && i < line.Length - 1 && line[i] == line[i + 1])
            {
                merged.Add(line[i] * 2);
                skip = true;
            }
            else
            {
                merged.Add(line[i]);
                skip = false;
            }
        }

        while (merged.Count < GridSize)
        {
            merged.Add(0);
        }

        return merged.ToArray();
    }
}
